package com.example.springboot159.springboot.chapter03;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;

public  abstract  class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{
    private static final Logger log = LoggerFactory.getLogger(AbstractAutowireCapableBeanFactory.class);
    private InstantiationStrategy strategy = new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {
        Object obj = null;
        try {
            log.info("createBean...");
            obj = beanDefinition.getBean().newInstance();
        } catch (InstantiationException e) {
            throw  new Exception("create bean error");
        }
        addSingleton(beanName,obj);
        return obj;
    }

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws Exception {
        Object obj = null;
        try {
            log.info("createBean...");
            obj = instantitation(beanName,beanDefinition,args);
        } catch (InstantiationException e) {
            throw  new Exception("create bean error");
        }
        addSingleton(beanName,obj);
        return obj;
    }


    protected Object instantitation(String beanName, BeanDefinition beanDefinition, Object[] args) throws Exception {
        Constructor real = null;
        Constructor<?>[] ctor = null;
        Class<?> beanClazz = beanDefinition.getBean();
        ctor = beanDefinition.getBean().getDeclaredConstructors();
        try {
            for (Constructor var:ctor){
                if (null != var && var.getParameterTypes().length == args.length){
                    real = var;
                    break;
                }
            }
        } catch (Exception e) {
            throw  new Exception("create bean error");
        }

        return strategy.instantiation(beanDefinition,beanName,real,args);
    }
}
